
inline vec2::vec2( float x0/* = 0.0f*/, float y0/* = 0.0f*/) : 
	x(x0), y(y0)
{
	SLMATH_VEC_ASSERT( check() );
}

inline void vec2::set( float x0, float y0 )
{
	x=x0;
	y=y0;
	SLMATH_VEC_ASSERT( check() );
}

inline vec2& vec2::operator+=( const vec2& o )
{
	x += o.x;
	y += o.y;
	SLMATH_VEC_ASSERT( check() );
	return *this;
}

inline vec2& vec2::operator-=( const vec2& o )
{
	x -= o.x;
	y -= o.y;
	SLMATH_VEC_ASSERT( check() );
	return *this;
}

inline vec2& vec2::operator*=( float s )
{
	x *= s;
	y *= s;
	SLMATH_VEC_ASSERT( check() );
	return *this;
}

inline vec2& vec2::operator/=( float s )
{
	SLMATH_VEC_ASSERT( check() );
	SLMATH_VEC_ASSERT( fabsf(s) >= FLT_MIN ); // s must be != 0
	const float sinv = 1.f/s;
	x *= sinv;
	y *= sinv;
	return *this;
}

inline vec2 vec2::operator/( float s ) const
{
	SLMATH_VEC_ASSERT( check() );
	SLMATH_VEC_ASSERT( fabsf(s) >= FLT_MIN ); // s must be != 0
	const float sinv = 1.f/s;
	return vec2( x*sinv, y*sinv );
}

inline vec2& vec2::operator*=( const vec2& o )
{
	SLMATH_VEC_ASSERT( o.check() );
	SLMATH_VEC_ASSERT( (*this).check() );
	x *= o.x;
	y *= o.y;
	return *this;
}

inline vec2& vec2::operator/=( const vec2& o )
{
	SLMATH_VEC_ASSERT( o.check() );
	SLMATH_VEC_ASSERT( (*this).check() );
	SLMATH_VEC_ASSERT( fabsf(o.x) > FLT_MIN );
	SLMATH_VEC_ASSERT( fabsf(o.y) > FLT_MIN );
	x /= o.x;
	y /= o.y;
	return *this;
}

inline vec2 vec2::operator*( const vec2& o ) const
{
	SLMATH_VEC_ASSERT( o.check() );
	SLMATH_VEC_ASSERT( (*this).check() );
	return vec2(x*o.x, y*o.y);
}

inline vec2 vec2::operator/( const vec2& o ) const
{
	SLMATH_VEC_ASSERT( o.check() );
	SLMATH_VEC_ASSERT( (*this).check() );
	SLMATH_VEC_ASSERT( fabsf(o.x) > FLT_MIN );
	SLMATH_VEC_ASSERT( fabsf(o.y) > FLT_MIN );
	return vec2(x/o.x,y/o.y);
}

inline vec2 vec2::operator+( const vec2& o ) const
{
	SLMATH_VEC_ASSERT( o.check() );
	SLMATH_VEC_ASSERT( (*this).check() );
	return vec2(x+o.x,y+o.y);
}

inline vec2 vec2::operator-( const vec2& o ) const
{
	SLMATH_VEC_ASSERT( o.check() );
	SLMATH_VEC_ASSERT( (*this).check() );
	return vec2(x-o.x,y-o.y);
}

inline vec2 vec2::operator-() const
{
	SLMATH_VEC_ASSERT( (*this).check() );
	return neg();
}

inline vec2 vec2::operator*( float s ) const
{
	SLMATH_VEC_ASSERT( slm::check(s) );
	SLMATH_VEC_ASSERT( (*this).check() );
	return vec2(x*s,y*s);
}

inline bool vec2::operator==( const vec2& o ) const
{
	return x==o.x && y==o.y;
}

inline bool vec2::operator!=( const vec2& o ) const
{
	return !(*this == o);
}

inline float vec2::length()const
{
	float res = sqrtf( lengthSq() );
	SLMATH_VEC_ASSERT( res >= 0.f && res <= FLT_MAX );
	return res;
}

inline float vec2::lengthSq()const
{
	SLMATH_VEC_ASSERT( (*this).check() );

	float res = x*x + y*y;

	SLMATH_VEC_ASSERT( res >= 0.f && res <= FLT_MAX );
	return res;
}

inline float vec2::dot( const vec2& a)const
{
	SLMATH_VEC_ASSERT( a.check() );
	SLMATH_VEC_ASSERT( (*this).check() );

	float res = a.x*x + a.y*y;

	SLMATH_VEC_ASSERT( res >= -FLT_MAX && res <= FLT_MAX );
	return res;
}

inline vec2 vec2::abs()const
{
	return vec2( fabsf(_v[0]), fabsf(_v[1]) );
}

inline vec2 vec2::mix(const vec2& v, float a )const
{
	return vecMix( *this, v, a );
}

inline float vec2::distance(const vec2& p1 )const
{
	float res = sqrtf(distanceSq(p1));
	SLMATH_VEC_ASSERT( res >= -FLT_MAX && res <= FLT_MAX );
	return res;
}

inline float vec2::distanceSq(const vec2& p1 )const
{
	return (*this - p1).lengthSq();
}

inline vec2 vec2::clamp(const vec2& min, const vec2& max )const
{
	return vecClamp( *this, min, max );
}

inline vec2 vec2::saturate()const
{
	return vecSaturate( *this );
}

inline bool vec2::check()const
{
	return x<=FLT_MAX && x>=-FLT_MAX && y<=FLT_MAX && y>=-FLT_MAX;
}

inline vec2 vec2::neg()const
{
	return vec2(-x, -y);
}

inline vec2 vec2::add(const vec2& b )const
{
	return vec2(*this+b);
}

inline vec2 vec2::sub(const vec2& b )const
{
	return vec2(*this-b);
}

inline float vec2::cross(const vec2& v)const
{
	return x * v.y - y * v.x;
}

inline vec2& vec2::operator-=( float s )
{
	x -= s; 
	y -= s; 
	return *this;
}

inline vec2& vec2::operator+=( float s )
{
	x += s;
	y += s;
	return *this;
}

#ifdef SLMATH_AUTO_DX_CONVERSION
inline vec2& vec2::operator = (const D3DXVECTOR2& dxv2)
{
	this->x = dxv2.x;
	this->y = dxv2.y;
	return *this;
}

inline vec2::operator D3DXVECTOR2()const
{
	return D3DXVECTOR2(x, y);
}
#endif // SLMATH_AUTO_DX_CONVERSION

inline std::ostream& operator << (std::ostream& stream, const vec2& v)
{
	stream << "vec2(" << v.x << "," << v.y << ")";
	return stream;
}

inline std::wostream& operator << (std::wostream& stream, const vec2& v)
{
	stream << L"vec2(" << v.x << L"," << v.y << L")";
	return stream;
}

inline vec2 operator * (float fv, const vec2& v2)
{
	return v2 * fv;
}

inline vec2 max( const vec2& a, const vec2& b )
{
	return vec2( max(a[0],b[0]), max(a[1],b[1]) );
}

inline vec2 min( const vec2& a, const vec2& b )
{
	return vec2( min(a[0],b[0]), min(a[1],b[1]) );
}

inline bool check(const vec2& v)
{
	return v.check();
}

// This file is part of 'slm' C++ library. Copyright (C) 2009 Jani Kajala (kajala@gmail.com). See http://sourceforge.net/projects/slm/
